package ar.com.fiuba.ElectronicCircuitAnalyst.application.impl;

import org.apache.log4j.Logger;

import ar.com.fiuba.ElectronicCircuitAnalyst.application.api.ComponentDto;
import ar.com.fiuba.ElectronicCircuitAnalyst.application.api.ComponentService;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.Component;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.ComponentFactory;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.repository.ComponentRepository;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.repository.DuplicateElementException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.api.repository.ElementNotFoundException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.AlreadyExistingCircuitElementException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.CircuitElementNotFoundException;
import ar.com.fiuba.ElectronicCircuitAnalyst.domain.exceptions.InvalidCircuitElementException;

public class ComponentServiceImpl implements ComponentService {

	private Logger log = Logger.getLogger(ComponentServiceImpl.class);

	private ComponentFactory componentFactory;

	private ComponentRepository componentRepository;

	public ComponentServiceImpl(ComponentFactory componentFactory, ComponentRepository componentRepository) {
		this.componentFactory = componentFactory;
		this.componentRepository = componentRepository;
	}

	public Component makeComponent(ComponentDto data) throws InvalidCircuitElementException,
			AlreadyExistingCircuitElementException {
		log.info("Making \"" + data.getName() + "\" component");
		Component theComponent = componentFactory.makeComponent(data);
		try {
			componentRepository.save(theComponent);
		} catch (DuplicateElementException e) {
			throw new AlreadyExistingCircuitElementException("Component with name \"" + data.getName()
					+ "\" already exists.");
		}
		return theComponent;
	}

	public Component modifyComponent(ComponentDto data) throws InvalidCircuitElementException,
			CircuitElementNotFoundException {
		log.info("Modifying \"" + data.getName() + "\" component.");
		removeComponent(data.getName());
		try {
			return makeComponent(data);
		} catch (AlreadyExistingCircuitElementException e) {
			// Should never reach this since component has just been removed,
			// but just in case...
			throw new RuntimeException("Unreachable code reached...");
		}
	}

	public Component getComponent(String name) throws CircuitElementNotFoundException {
		log.info("Retrieving \"" + name + "\" component.");
		return componentRepository.getComponentByName(name);
	}

	public void removeComponent(String name) throws CircuitElementNotFoundException {
		log.info("Removing \"" + name + "\" component.");
		try {
			componentRepository.remove(componentRepository.getComponentByName(name));
		} catch (ElementNotFoundException e) {
			throw new CircuitElementNotFoundException("Component with name \"" + name + "\" could not be found.");
		}
	}
}
